package com.h6.crm.handler;

import java.util.ArrayList;

import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import com.h6.crm.util.pojo.ErrorR;
import com.h6.crm.util.pojo.ResultCode;
import com.h6.crm.util.pojo.ServiceException;

import cn.hutool.core.util.StrUtil;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;

/**
 * 全局异常处理类
 * 
 * @RestControllerAdvice(@ControllerAdvice)，拦截异常并统一处理
 *
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    /**
     * 处理自定义的业务异常
     * 
     * @param e       异常对象
     * @param request request
     * @return 错误结果
     */
    @ExceptionHandler(ServiceException.class)
    public ErrorR ServiceExceptionHandler(ServiceException e, HttpServletRequest request) {
        log.error("发生业务异常！原因是: {}", e.getMessage());
        return ErrorR.fail(e.getCode(), e.getMessage());
    }

    // 拦截抛出的异常，@ResponseStatus：用来改变响应状态码
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(Throwable.class)
    public ErrorR handlerThrowable(Throwable e, HttpServletRequest request) {
        log.error("发生未知异常！原因是: ", e);
        return ErrorR.fail(ResultCode.SYSTEM_ERROR, e);
    }

    // 参数校验异常
    @ExceptionHandler(BindException.class)
    public ErrorR handleBindExcpetion(BindException e, HttpServletRequest request) {
        BindingResult bindingResult = e.getBindingResult();
        // 存放错误信息
        String errMessage = getAllErrMessage(bindingResult);
        log.error("发生参数校验异常！原因是：", e);
        return ErrorR.fail(ResultCode.PARAM_IS_INVALID, e, errMessage);
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ErrorR handleMethodArgumentNotValidException(MethodArgumentNotValidException e,
            HttpServletRequest request) {
        BindingResult bindingResult = e.getBindingResult();
        String errMessage = getAllErrMessage(bindingResult);
        log.error("发生参数校验异常！原因是：", e);
        return ErrorR.fail(ResultCode.PARAM_IS_INVALID, e, errMessage);
    }

    private static String getAllErrMessage(BindingResult bindingResult) {
        // 存放错误信息
        ArrayList<String> errors = new ArrayList<>();
        bindingResult.getFieldErrors().forEach(item -> {
            errors.add(item.getDefaultMessage());
        });
        return StrUtil.join(",", errors);
    }
}
